﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace DataAchive.Server
{
    public class HttpServer : IDisposable
    {
        public HttpServer() { }


        private static HttpListener httpobj;
        public void Start(string IP, string Port, string Api)
        {
            try
            {

                //提供一个简单的、可通过编程方式控制的 HTTP 协议侦听器。此类不能被继承。
                httpobj = new HttpListener();
                //定义url及端口号，通常设置为配置文件
                httpobj.Prefixes.Add($"http://{IP}:{Port}/{Api}/");
                //启动监听器
                if (httpobj != null && !httpobj.IsListening)
                {
                    httpobj.Start();
                    //异步监听客户端请求，当客户端的网络请求到来时会自动执行Result委托
                    //该委托没有返回值，有一个IAsyncResult接口的参数，可通过该参数获取context对象
                    httpobj.BeginGetContext(Result, null);
                }
            }
            catch (Exception ex)
            {
                SoftCommon.Log.Write(SoftCommon.LogType.Error, $"服务端启动失败：{ex.Message}");
                return;
            }
        }

        private void Result(IAsyncResult ar)
        {
            //当接收到请求后程序流会走到这里
            // 如果 HttpListener 已经关闭，则直接返回
            if (httpobj == null || !httpobj.IsListening)
                return;

            SoftCommon.Log.Write($"接到新的请求,时间：{DateTime.Now.ToString()}\r\n");
            //获得context对象
            var context = httpobj.EndGetContext(ar);
            var request = context.Request;
            var response = context.Response;
            ////如果是js的ajax请求，还可以设置跨域的ip地址与参数
            context.Response.ContentType = "text/plain;charset=UTF-8";//告诉客户端返回的ContentType类型为纯文本格式，编码为UTF-8
            context.Response.AddHeader("Content-type", "text/plain");//添加响应头信息
            context.Response.ContentEncoding = Encoding.UTF8;
            object returnObj = null;//定义返回客户端的信息
            if (request.HttpMethod == "POST" && request.InputStream != null)
            {
                //处理客户端发送的请求并返回处理信息
                returnObj = HandleRequest(request, response);
            }
            else
            {
                returnObj = $"不是post请求或者传过来的数据为空";
            }
            var returnByteArr = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(returnObj));//设置客户端返回信息的编码
            try
            {
                using (var stream = response.OutputStream)
                {
                    //把处理信息返回到客户端
                    stream.Write(returnByteArr, 0, returnByteArr.Length);
                }
            }
            catch (Exception ex)
            {
                SoftCommon.Log.Write($"异常：{ex.ToString()}\r\n");
            }
            SoftCommon.Log.Write($"请求处理完成,时间：{DateTime.Now.ToString()}\r\n");

            //继续异步监听
            httpobj.BeginGetContext(Result, null);
        }

        private string HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
        {
            string data = null;
            try
            {
                var byteList = new List<byte>();
                var byteArr = new byte[2048];
                int readLen = 0;
                int len = 0;
                //接收客户端传过来的数据并转成字符串类型
                do
                {
                    readLen = request.InputStream.Read(byteArr, 0, byteArr.Length);
                    len += readLen;
                    byteList.AddRange(byteArr);
                } while (readLen != 0);
                data = Encoding.UTF8.GetString(byteList.ToArray(), 0, len);
            }
            catch (Exception ex)
            {
                response.StatusDescription = "404";
                response.StatusCode = 404;
                SoftCommon.Log.Write($"在接收数据时发生错误:{ex.ToString()}\r\n");
                //return $"在接收数据时发生错误:{ex.ToString()}";//把服务端错误信息直接返回可能会导致信息不安全，此处仅供参考
            }
            response.StatusDescription = "200";//获取或设置返回给客户端的 HTTP 状态代码的文本说明。
            response.StatusCode = 200;// 获取或设置返回给客户端的 HTTP 状态代码。
            SoftCommon.Log.Write($"接收数据完成,时间：{DateTime.Now.ToString()}\r\n");
            return data;
        }


        public void Stop()
        {
            try
            {
                //关闭监听器
                if (httpobj != null && httpobj.IsListening)
                {
                    httpobj.Close();
                    httpobj = null; // 设置为 null，表示对象已经释放
                }
            }
            catch (Exception ex)
            {
                SoftCommon.Log.Write(SoftCommon.LogType.Error, $"服务监听器关闭失败：{ex.Message}");
                return;
            }

        }




        public void Dispose()
        {

        }
    }
}
